﻿function setParent(el, newParent)
{
    newParent.appendChild(el);
}

SSVC.Wrap.Dojo.Declare("Container", SSVC.SVG.Shape,
{
    NodeType: "svg",
    Marker: null,

    ActionMode: null,

    SelectedElements: null,
    CurrentObject: null,

    selectionRect: null,

    OnDrawingEnd: null,

    CurrentDrawableElement: null,
    Properties: null,

    Actions:
    {
        Selecting: "selecting",
        Moving: "moving",
        Drawing: "drawing",
        None: "none"
    },

    AffectedKey:
    {
        SHIFT: 16,
        CTRL: 17,
        ENTER: 13,
        ALT: 18,
        ESCAPE: 27,
        DEL: 46
    },

    constructor: function()
    {
        this.Class = "Container";

        this.ActionMode = this.Actions.None;
        this.SelectedElements = [];
        this.SelectedPoint = null;

        this._createMarker();

        SSVC.Wrap.Dojo.On(this.Node, "mousedown", SSVC.Wrap.Dojo.Partial(this.OnMouseDown, this));
        SSVC.Wrap.Dojo.On(this.Node, "mouseup", SSVC.Wrap.Dojo.Partial(this.OnMouseUp, this));
        SSVC.Wrap.Dojo.On(this.Node, "mousemove", SSVC.Wrap.Dojo.Partial(this.OnMouseMove, this));
        SSVC.Wrap.Dojo.On(this.Node, "keydown", SSVC.Wrap.Dojo.Partial(this.OnKeyDown, this));
    },

    OnMouseDown: function(callElement)
    {
        var x = arguments[1].offsetX === undefined ? arguments[1].layerX : arguments[1].offsetX;
        var y = arguments[1].offsetY === undefined ? arguments[1].layerY : arguments[1].offsetY;

        callElement.SelectedPoint = { x: x, y: y };

        if (callElement.ActionMode === callElement.Actions.Drawing)
        {
            callElement.CurrentObject = new callElement.CurrentDrawableElement();
            callElement.CurrentObject.AddProperties(callElement.Properties);
            callElement.addChild(callElement.CurrentObject);
            callElement.CurrentObject.Draw(callElement.SelectedPoint.x, callElement.SelectedPoint.y, x, y, arguments[1].shiftKey);
            callElement.deselectAll();

            return;
        }
        else
        {
            var selectedElement = callElement._getChildByPoint(callElement.SelectedPoint);

            if (!selectedElement)
            {
                if (callElement.selectionRect !== null)
                    callElement._destroyCurrentGroupSelection();

                callElement.ActionMode = callElement.Actions.Selecting;
                callElement.deselectAll();
                callElement._createCurrentGroupSelection();
                return;
            }

            callElement.ActionMode = callElement.Actions.Moving;

            if (selectedElement && (arguments[1].ctrlKey || arguments[1].shiftKey))
            {
                callElement.select(selectedElement);
            }
            else
                callElement.selectOnly(selectedElement);
        }
    },

    OnMouseUp: function(callElement)
    {
        callElement.SelectedPoint = null;
        if (callElement.ActionMode === callElement.Actions.Drawing)
            callElement.CurrentObject.Deselect();
        if (callElement.ActionMode === callElement.Actions.Moving && callElement.SelectedElements.length === 1)
            callElement.selectOnlyCurrent();

        if (callElement.selectionRect !== null && callElement.ActionMode === callElement.Actions.Selecting)
        {
            callElement._setCurrentGroupSelection();

            if (callElement.SelectedElements.length === 0)
            {
                callElement._destroyCurrentGroupSelection();
                return;
            }
            
            callElement.ActionMode = callElement.Actions.Moving;

            callElement.CurrentObject = callElement.selectionRect;
            callElement._destroyCurrentGroupSelection();
        }
    },

    OnMouseMove: function(callElement)
    {
        var offsetX = arguments[1].offsetX === undefined ? arguments[1].layerX : arguments[1].offsetX;
        var offsetY = arguments[1].offsetY === undefined ? arguments[1].layerY : arguments[1].offsetY;
        var evt = arguments[1];
        if (callElement.SelectedPoint === null) return;

        if (callElement.ActionMode === callElement.Actions.Selecting)
        {
            if (callElement.selectionRect !== null)
            {
                callElement.selectionRect.Draw(callElement.SelectedPoint.x, callElement.SelectedPoint.y, offsetX, offsetY, false);
            }
        }
        else
            if (callElement.ActionMode === callElement.Actions.Moving)
            {
                callElement.CurrentObject.Cursor = SSVC.SVG.ActiveElement.Enums.Cursors.Move;
                callElement.CurrentObject.Move(offsetX, offsetY, arguments[1].shiftKey);
            }
            else
                if (callElement.ActionMode === callElement.Actions.Drawing)
                {
                    callElement.CurrentObject.Draw(callElement.SelectedPoint.x, callElement.SelectedPoint.y, offsetX, offsetY, arguments[1].shiftKey);
                }
    },

    OnKeyDown: function(callElement)
    {
        if (arguments[1].keyCode === callElement.AffectedKey.DEL || arguments[1].keyCode === 123)
            callElement.removeSelected();
    },

    OnStartDrawing: function()
    { },

    _moveSelectedElements: function(x, y)
    {
        var deltaX = this.SelectedPoint.x - x;
        var deltaY = this.SelectedPoint.y - y;
        var newx = this.selectionRect.X;
        var newy = this.selectionRect.Y;

        newx -= deltaX;
        newy -= deltaY;
        //for (var i in this.SelectedElements)
        //{
        //	this.SelectedElements[i].selectedPoint = this.SelectedPoint;
        //	this.SelectedElements[i].Move(deltaX, deltaY, false);
        //}

        //var matrix = this.Node.createSVGMatrix();
        //matrix = matrix.translate(newx, newy);
        //if (this.selectionRect.Node.transform.baseVal.numberOfItems === 0)
        //{
        //	this.selectionRect.Node.transform.baseVal.createSVGTransformFromMatrix(matrix);
        //	var transformObject = this.Node.createSVGTransform();
        //	this.selectionRect.Node.transform.baseVal.appendItem(transformObject);
        //}
        //else
        //	this.selectionRect.Node.transform.baseVal.getItem(0).setMatrix(matrix);
    },

    _getChildByPoint: function(point)
    {
        for (var i in this.Childs)
        {
            var startX = this.Childs[i].Node.getBBox().x;
            var startY = this.Childs[i].Node.getBBox().y;
            var endX = startX + this.Childs[i].Node.getBBox().width;
            var endY = startY + this.Childs[i].Node.getBBox().height;
            if ((point.x >= startX && point.x <= endX) && (point.y >= startY && point.y <= endY)) return this.Childs[i];
        }

        return null;
    },

    _selectChildsByPoint: function(point)
    {
        for (var i in this.Childs)
        {
            var startX = this.Childs[i].Node.getBBox().x;
            var startY = this.Childs[i].Node.getBBox().y;
            var endX = startX + this.Childs[i].Node.getBBox().width;
            var endY = startY + this.Childs[i].Node.getBBox().height;
            if ((startX > point.x && point.x + point.width > endX) && (startY > point.y && point.y + point.height > endY))
                this.select(this.Childs[i]);
        }
    },

    _createCurrentGroupSelection: function()
    {
        this.selectionRect = new SSVC.SVG.ActiveElement();
        this.selectionRect.AddProperties({ strokeWidth: 0, lineColor: "transparent", strokeDash: "none" });
        this.addChild(this.selectionRect);
        this.CurrentObject = this.selectionRect;
    },

    _setCurrentGroupSelection: function()
    {
        this._selectChildsByPoint(this.selectionRect.Node.getBBox());
        for (var i in this.SelectedElements)
        {
            //future tascl fo multiple resizing-moving
            //this.selectionRect.Node.appendChild(this.SelectedElements[i].Node);
        }
    },

    _destroyCurrentGroupSelection: function()
    {
        for (var i in this.SelectedElements)
        {
            //this.Node.appendChild(this.SelectedElements[i].Node);
        }
        //this.SelectedElements = [];
        try
        {
            this.Node.removeChild(this.selectionRect.Node);
        }
        catch (e)
        {
            console.log(e.description);
        }
        this.selectionRect = null;
    },

    _createMarker: function()
    {
        this.Marker = new SSVC.SVG.Marker("Triangle", "M 0 0 L 20 10 L 0 20 z");
        this.Marker.update(0, 10, 8, 6);

        this.Node.appendChild(this.Marker.defs);
    },

    selectAll: function()
    {
        this.SelectedElements = [];

        for (var i in this.Childs)
        {
            this.SelectedElements.push(this.Childs[i]);
            this.Childs[i].Select();
        }
    },

    selectOnly: function(element)
    {
        this.deselectAll();

        this.select(element);
    },

    selectOnlyCurrent: function()
    {
        this.SelectedElements = [];
        for (var i in this.Childs)
        {
            if (this.CurrentObject.ID === this.Childs[i].ID)
            {
                this.select(this.Childs[i]);
                continue;
            }
            this.Childs[i].Deselect();
        }
    },

    select: function(element)
    {
        element.Select();
        this.CurrentObject = element;
        this.SelectedElements.push(element);
    },

    deselect: function(index)
    {
        this.SelectedElements[index].Deselect();
        this.SelectedElements.splice(index, 1);
    },

    deselectAll: function()
    {
        while (this.SelectedElements.length !== 0)
        {
            this.deselect(0);
        }
    },

    removeSelected: function()
    {
        while (this.SelectedElements.length!==0)
        {
            this.remove(this.SelectedElements[0]);
            this.deselect(0);
        }
    },

    remove: function(element)
    {
        for (var j in this.Childs)
        {
            if (this.Childs[j].ID === element.ID)
            {
                this.Childs[j].Delete();
                this.Childs.splice(j, 1);
            }
        }
    },

    getSelected: function()
    {
        for (var i in this.Childs)
        {
            if (this.Childs[i].SelectMode === SSVC.SVG.ActiveElement.Enums.SelectMode.Selected)
                this.SelectedElements.push(this.Childs[i]);
        }
    },

    Scale: function(factorX, factorY)
    {
        for (var i = 0;i < this.Childs.length;i++)
        {
            if (factorX !== 1)
                this.Childs[i].ScaleX(factorX);

            if (factorY !== 1)
                this.Childs[i].ScaleY(factorY);
        }
    },

    GetOuterXml: function()
    {
        return this.getXml();
    },

    /// params: SSVC.SVG.ActiveElement
    StartDrawing: function(drawableElement, drawingProperties)
    {
        this.ActionMode = this.Actions.Drawing;
        this.CurrentDrawableElement = drawableElement;
        this.Properties = drawingProperties;
    },

    /// params: SSVC.SVG.ActiveElement
    StartMoving: function(movableElement)
    {
        this.getSelected();
        this.ActionMode = this.Actions.Moving;
    },

    DestroyActions: function()
    {
        this.CurrentObject = null;
        this.ActionMode = this.Actions.None;
    },

    GetXml: function(element)
    {
        if (!element || element === null) element = this;

        var outerXml = element.GetOuterXml();

        var childsXml = "";
        for (var i = 0;i < this.Childs.length;i++)
        {
            try
            {
                var childNode = element.Childs[i].GetOuterXml();
                outerXml.appendChild(childNode);
            }
            catch (e)
            {
                console.error(e.message);
                continue;
            }
        }
        return outerXml;
    },

    ApplyXml: function(xmlstr)
    {
        var xml = SSVC.Wrap.Dojo.Xml.parse(xmlstr);
        this.applyXml(xml.documentElement);
        for (var i = 0;i < xml.documentElement.childNodes.length;i++)
        {
            var child = SSVC.SVG.ActiveElement.XmlDeserialize(xml.documentElement.childNodes[i]);
            this.addChild(child);
        }

        this.deselectAll();
    },

    removeChilds: function()
    {
        for (var j in this.Childs)
        {
            this.Childs[j].Delete();
            this.Childs.splice(j, 1);
        }
        this.Childs = [];
    }
});

SSVC.Wrap.Dojo.SetObject("SSVC.SVG.Container", Container);
